/******************************************************************************
Module:  Singleton.cs
Notices: Copyright (c) 2006-2007 by Jeffrey Richter and Wintellect
******************************************************************************/


using System;
using System.Threading;


///////////////////////////////////////////////////////////////////////////////


namespace Microsoft.OfficeCommunicationsServer.Applications.Threading.Threading {
   public enum SingletonRaceLoser {
      Block = 0,
      GC = 1,
   }

   public sealed class Singleton<T> where T: class {
      private SingletonRaceLoser m_raceLoser = SingletonRaceLoser.Block;

      public delegate T Creator();
      private Creator m_creator = null;

      private T m_value = null;

      public Singleton(SingletonRaceLoser raceLoser, Creator creator) {
         m_raceLoser = raceLoser;
         m_creator = creator;
      }

      public T Value {
         get {
            if (m_value != null) return m_value;
            switch (m_raceLoser) {
               case SingletonRaceLoser.Block:
                  lock (m_creator) {
                     if (m_value == null) m_value = m_creator();
                  }
                  break;

               case SingletonRaceLoser.GC:
                  T val = m_creator();
                  if (Interlocked.CompareExchange(ref m_value, val, null) != null) {
                     IDisposable d = val as IDisposable;
                     if (d != null) d.Dispose();
                  }
                  break;
            }
            return m_value;
         }
      }
   }
}


//////////////////////////////// End of File //////////////////////////////////
